#include <iostream>
#include <memory>
#include <string>
#include <ctype.h>
#include <cstdio>
#include "udp_server.hpp"
#include "err.h"

using namespace std;
using namespace udp_server;

// 上层的业务处理不关心网络信息的收发，只关心对网络信息的处理
//  处理业务1:客户端输入的数据出现小写字母，将小写字母转化为大写字母
string ToUpper(string s)
{
    string temp;
    for (auto e : s)
    {
        if (islower(e)) // 小写字母转大写字母
        {
            char c = toupper(e);
            temp.push_back(c);
        }
        else
            temp.push_back(e);
    }
    return temp;
}

// 处理业务2:客户端输入指令，服务器返回输入这个指令出现的结果
string CommandResult(string command)
{
    FILE *fp;
    char buffer[1024];
    string temp;
    /*安全检查*/
    bool pass = true;
    if (command.find("rm") != string::npos)
        pass = false;
    if (command.find("mv") != string::npos)
        pass = false;
    if (command.find("while") != string::npos)
        pass = false;
    if (!pass)
        temp = "you are bad man!";
    if (pass)
    {
        // 1. 执行一个命令并打开一个管道连接到它
        fp = popen(command.c_str(), "r");
        if (fp == nullptr)
        {
            cerr << "popen error:" << strerror(errno) << endl;
            exit(POPEN_ERROR);
        }
        // 2.读取指令结果
        while (fgets(buffer, sizeof(buffer), fp) != nullptr)
        {
            temp += buffer;
        }
    }
    pclose(fp);
    // 3.返回指令结果
    return temp;
}

//./server port
void Usage(string u)
{
    cout << "Usage:\n\t" << u << " port" << endl;
}
int main(int argv, char *argc[])
{
    // UdpServer s;
    // cout<<"me is server"<<endl;
    /*使用说明*/
    if (argv != 2)
    {
        Usage(argc[0]);
        exit(USAGE_ERROR);
    }
    uint16_t port = atoi(argc[1]); // 将字符串转化为数字端口号
    cout << "port:" << port << endl;
    // 1.使用智能指针管理服务器类：当智能指针被释放，类也被释放
    // unique_ptr<UdpServer> usvr(new UdpServer(port));

    // 处理业务1
    // unique_ptr<UdpServer> usvr(new UdpServer(port, ToUpper));

    // 处理业务2
    // unique_ptr<UdpServer> usvr(new UdpServer(port, CommandResult));
    
    //处理业务3
    unique_ptr<UdpServer> usvr(new UdpServer(port));
    usvr->start();
    
    return 0;
}
